/*
 * Copyright (C) 2004-2010  Autodesk, Inc.
 * 
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of version 2.1 of the GNU Lesser
 * General Public License as published by the Free Software Foundation.
 * 
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 */

#include <stdafx.h>
#include <OWS/FdoOwsGetCapabilities.h>
#include <OWS/FdoOwsResponse.h>
#include "FdoCMSYahooDelegate.h"
#include "FdoCMSYahooGetMap.h"
#include "FdoCMSYahooGetMapURL.h"
#include "FdoCMSXmlGlobals.h"
#include "FdoCMSGlobals.h"
#include "FdoCMSBoundingBox.h"

#include "FdoCommonThreadUtil.h"

FdoCMSYahooDelegate::FdoCMSYahooDelegate()
{
    FdoCMSYahooDelegate(NULL,NULL);
}

FdoCMSYahooDelegate::FdoCMSYahooDelegate(FdoString* serviceUrl,FdoString* apiKey) :
     FdoCMSDelegate(serviceUrl, apiKey)
{
    _InitZoomLevel();
}

FdoCMSYahooDelegate::~FdoCMSYahooDelegate()
{
}

void FdoCMSYahooDelegate::Dispose()
{ 
    delete this; 
}

FdoBoolean FdoCMSYahooDelegate::TestConnection()
{
    return true;
}



GDALDataset*
FdoCMSYahooDelegate::GetMapGdalDataset(FdoCMSBoundingBox* bbox,
                                      FdoSize height,
                                      FdoSize width,
                                      FdoString* mapType,
                                      FdoDouble& retScale)
{
    VALIDATE_ARGUMENT (bbox);
    VALIDATE_ARGUMENT (mapType);

    FdoSize heightOut = height;
    FdoSize widthOut = width;
    FdoInt32 zoomLevel = 0;

    FdoStringP url;
    FdoDouble ver;
    if(0 == FdoCommonStringUtil::StringCompareNoCase(mapType, FdoCMSGlobals::MapFormat_Google_roadmap))
    {
        url = L"http://maps3.yimg.com/hx/tl?";
        ver = 4.3;
    }
    else if(0 == FdoCommonStringUtil::StringCompareNoCase(mapType, FdoCMSGlobals::MapFormat_Google_satellite))
    {
        url = L"http://maps3.yimg.com/ae/ximg?";
        ver = 1.9;
    }
    else
    {
        assert(0);
    }
    this->SetUrl(url);  
    
    if(SplitImageNeeded(bbox, height, width, FdoCMSXmlGlobals::CMSYahooMaxZoomLevel, heightOut, widthOut, zoomLevel))
    {
        return SplitImageYahoo(bbox, zoomLevel, heightOut, widthOut, ver, url);
    }
    assert(0);
    return NULL;
}

GDALDataset*
FdoCMSYahooDelegate::SplitImageYahoo(FdoCMSBoundingBox* bbox
                , FdoInt32 zoomLevel
                , FdoSize heightMatched
                , FdoSize widthMatched
                , FdoDouble ver
                , FdoString* url)
{
    FdoInt32 minX = FdoCMSBoundingBox::long2tilex(bbox->GetMinX(), zoomLevel);
    FdoInt32 minY = FdoCMSBoundingBox::lat2tiley(bbox->GetMaxY(), zoomLevel);
    FdoInt32 maxX = FdoCMSBoundingBox::long2tilex(bbox->GetMaxX(), zoomLevel);
    FdoInt32 maxY = FdoCMSBoundingBox::lat2tiley(bbox->GetMinY(), zoomLevel);

    FdoInt32 countY = maxY - minY + 1;
    FdoInt32 countX = maxX - minX + 1;
    
    int pixelXMin, pixelYMin, pixelYMax,pixelXMax;
    pixelXMin = pixelYMin = pixelXMax = pixelYMax = 0;
    FdoCMSBoundingBox::LatLongToPixelXY(bbox->GetMaxY(),bbox->GetMinX(),zoomLevel,pixelXMin, pixelYMin);
    FdoCMSBoundingBox::LatLongToPixelXY(bbox->GetMinY(),bbox->GetMaxX(),zoomLevel,pixelXMax, pixelYMax);

    assert(countY > 0);
    assert(countX > 0);
    FdoCMSImageSpaceTileManager* pTileManager = new FdoCMSImageSpaceTileManager(countY * MaxImageSize(), countX * MaxImageSize());
    pTileManager->SetXYCount(countX, countY);
    pTileManager->BeginWrite();

    FdoSize pixelX_start = 0;
    FdoSize pixelY_start = 0;
    
    FdoSize offsetY, offsetX;

    FdoSize tileHeight0, tileWidth0;
    tileWidth0 = GetTileSize(minX, minX, maxX, pixelXMin, pixelXMax);
    tileHeight0 = GetTileSize(minY, minY, maxY, pixelYMin, pixelYMax);
    int count = 0;

    for(int indexY = minY; indexY <= maxY; indexY++)
    {
        for(int indexX = minX; indexX <= maxX; indexX++)
        {
            FdoSize tileHeight, tileWidth;

            tileWidth = GetTileSize(indexX, minX, maxX, pixelXMin, pixelXMax);
            offsetX = GetOffset(indexX, minX, pixelXMin);
            tileHeight = GetTileSize(indexY, minY, maxY, pixelYMin, pixelYMax);
            offsetY = GetOffset(indexY, minY, pixelYMin);

            pixelX_start = GetPixelStart(indexX, minX, tileWidth0);
            pixelY_start = GetPixelStart(indexY, minY, tileHeight0);

            FdoSize iHeight = this->MaxImageSize();
            FdoSize iWidth = this->MaxImageSize();

            FdoCMSImageSpaceTile* pTile = new FdoCMSImageSpaceTile(offsetX,offsetY,tileHeight,tileWidth,iHeight,iWidth,pixelX_start,pixelY_start);
            pTile->SetTileXY(indexX, indexY);
            FdoSize indexXOut, indexYOut;
            pTileManager->AppendTile(pTile, indexXOut, indexYOut);
        }
    }
    pTileManager->EndWrite();
    int tileCount = countY * countX;
    int rasterBandNum = pTileManager->DoQueryYahoo(tileCount, url, zoomLevel, ver);
    return pTileManager->MergeImageTilesGDALYahoo(rasterBandNum, offsetX, offsetY, heightMatched, widthMatched);
}

FdoSize FdoCMSYahooDelegate::GetOffset(FdoSize index, int min, int pixelMin)                                                 
{
    return index == min? pixelMin - MaxImageSize()  * min: 0;
}

FdoSize FdoCMSYahooDelegate::GetTileSize(FdoSize index, int min, int max, int pixelMin, int pixelMax)                                       
{
    FdoSize size = this->MaxImageSize();
    if(index == min)
    {
        size -= GetOffset(index, min, pixelMin);
    }
    if(index == max)
    {
        FdoSize iTemp = (MaxImageSize()  * max + MaxImageSize()  - pixelMax);
        size -= iTemp;
    }
    return size;
}

FdoSize FdoCMSYahooDelegate::GetPixelStart(FdoSize index, int min, FdoSize tileSize0) 
{
    return index == min? 0:(index-min-1)*MaxImageSize()+tileSize0;
}
